﻿using System;
using System.Runtime.InteropServices;

namespace Tests.Diagnostics
{
    public class TooManyParameters : If
    {
        public static void F1(int p1, int p2, int p3) { }

        public static void F2(int p1, int p2, int p3, int p4) { } // Compliant, interface implementation

        public static void F1(int p1, int p2, int p3, int p4) { } // Noncompliant {{Method has 4 parameters, which is greater than the 3 authorized.}}
    }

    public interface If
    {
        static abstract void F1(int p1, int p2, int p3);
        static abstract void F2(int p1, int p2, int p3, int p4); // Noncompliant
    }

    public unsafe partial class LibraryImportAttributeImports
    {
        [LibraryImport("foo.dll")]
        public static partial void ExternWithoutMarshaling(int p1, int p2, int p3, int p4); // Compliant, external definition

        // Provide the implementation usually generated by the source generator:
        // Copy the partial definition with the LibraryImport attribute to a .Net 7 file and use GotoDefinition to see the generated code
        [System.Runtime.InteropServices.DllImportAttribute("foo.dll", EntryPoint = "Extern", ExactSpelling = true)]
        public static extern partial void ExternWithoutMarshaling(int p1, int p2, int p3, int p4);

        [LibraryImport("nativelib", EntryPoint = "ExternWithMarshaling", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial string ExternWithMarshaling(string str, int p1, int p2, int p3, int p4); // Compliant, external definition

        // Provide the implementation usually generated by the source generator.
        // Copy the partial definition with the LibraryImport attribute to a .Net 7 file and use GotoDefinition to see the generated code
        [System.Runtime.CompilerServices.SkipLocalsInitAttribute]
        internal static partial string ExternWithMarshaling(string str, int p1, int p2, int p3, int p4)
        {
            string __retVal;
            ushort* __retVal_native = default;
            try
            {
                // Pin - Pin data in preparation for calling the P/Invoke.
                fixed (void* __str_native = &global::System.Runtime.InteropServices.Marshalling.Utf16StringMarshaller.GetPinnableReference(str))
                {
                    __retVal_native = __PInvoke((ushort*)__str_native, p1, p2, p3, p4);
                }

                // Unmarshal - Convert native data to managed data.
                __retVal = global::System.Runtime.InteropServices.Marshalling.Utf16StringMarshaller.ConvertToManaged(__retVal_native);
            }
            finally
            {
                // Cleanup - Perform required cleanup.
                global::System.Runtime.InteropServices.Marshalling.Utf16StringMarshaller.Free(__retVal_native);
            }

            return __retVal;
            // Local P/Invoke
            [System.Runtime.InteropServices.DllImportAttribute("nativelib", EntryPoint = "ExternWithMarshaling", ExactSpelling = true)]
            static extern unsafe ushort* __PInvoke(ushort* str, int p1, int p2, int p3, int p4);
        }
    }
}
